﻿module Tokens



open System.Runtime.Serialization
open System
open System.IO
open Sources



[<DataContract>]
type Token(isBoxed, source, location) = 

   [<DataMember>]
   member val IsBoxed : bool = isBoxed with get, set

   [<DataMember>]
   member val Source : string = source with get, set

   [<DataMember>]
   member val Location : SourceLocation = location  with get, set
   


let ToString(tokens : seq<Token>) =
   let value = tokens |> Seq.map(fun t -> t.Source)
   String.Join(" ", value)



let ReadToken(reader : SourceReader) =  
   SkipIrrelevant(reader)    

   let location = reader.GetLocation()
   let source = ReadSource(reader)   

   if (source.IsSome) then
      let isBoxed = IsBoxed(source)
      Some(Token(isBoxed, source.Value, location))
   else
      None



let ReadDescription(reader : SourceReader) =
   SkipIrrelevant(reader)
    
   let starting = reader.GetLocation()

   let rec recurse(value : string, previous : char, returns : int) =      
      let peek = reader.Peek()

      if (returns > 1) then
         value
      elif (peek = -1) then
         ""
      else   
         let next = (char)(peek)      

         if (next = '{') then
            SkipComments(reader)
            recurse(value, ' ', 0)
         else
            let current = reader.Read()
            let value = value + current.ToString()

            // TODO: support?
//            if (current = '\n' && previous = '\n') then
//               value
            
            if (previous = '\r' && current = '\n') then
               recurse(value, current, returns + 1)
            elif (previous = '\n' && current = '\r') then
               recurse(value, current, returns)
            else
               recurse(value, current, 0)

   let source = recurse("", ' ', 0)

   if (source <> "") then            
      Some(Token(false, source.Substring(0, source.Length - 4), starting))
   else
      None